package test.SoundDriver;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.SystemClock;


public class Shaker extends Activity {
	private SensorManager mgr = null;
	private long lastShakeTimestamp = 0, lastSampleTimestamp;
	private double threshold = 1.0d;
	private long gap = 0;
	private Quantization myQ;
	private Shaker.Callback cb = null;
	
	public Shaker(Context ctxt, double threshold, long gap, Shaker.Callback cb) {
		this.threshold = threshold * threshold;
		this.threshold = this.threshold * SensorManager.GRAVITY_EARTH
				* SensorManager.GRAVITY_EARTH;
		this.gap = gap;
		this.cb = cb;		
		this.myQ = new Quantization();
		mgr = (SensorManager) ctxt.getSystemService(Context.SENSOR_SERVICE);
		mgr.registerListener(listener,
				mgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				SensorManager.SENSOR_DELAY_UI);
		mgr.registerListener(listener,
				mgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
				SensorManager.SENSOR_DELAY_UI);
	}

	public void close() {
		mgr.unregisterListener(listener);
	}

	private void isShaking() {
		long now = SystemClock.uptimeMillis();
		if (lastShakeTimestamp == 0) {
			lastShakeTimestamp = now;
			if (cb != null) {				
				//System.out.println("volume "+volume);				
				cb.shakingStarted();
			}
		} else {
			lastShakeTimestamp = now;
		}
	}

	private void isNotShaking() {
		long now = SystemClock.uptimeMillis();
		if (lastShakeTimestamp > 0) {
			if (now - lastShakeTimestamp > gap) {
				lastShakeTimestamp = 0;
				if (cb != null) {
					cb.shakingStopped();					
				}
			}
		}
	}

	public interface Callback {
		void shakingStarted();
		void shakingStopped();
	}

	public SensorEventListener listener = new SensorEventListener() {
		public void onSensorChanged(SensorEvent e) {
			if (e.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
				//unused;
			}
			if (e.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
					double netForce = e.values[0] * e.values[0];
					netForce += e.values[1] * e.values[1];
					netForce += e.values[2] * e.values[2];					
					if (netForce > threshold) {
						long sNow = SystemClock.uptimeMillis();
						if (lastSampleTimestamp == 0){
							lastSampleTimestamp = sNow;							
						}
						if (sNow - lastSampleTimestamp > 20){							
							if(!myQ.add(e.values)){
								myQ.smoothSamples();
								myQ.quantizeSamples();
								//other operations...
							}
						}		
						lastSampleTimestamp = sNow;
						isShaking();															
					} else {
						lastSampleTimestamp = 0;
						isNotShaking();
					}
			}
		}

		public void onAccuracyChanged(Sensor sensor, int accuracy) {
			// unused
		}
	};
	
}

